/**
 * 中文数组封装 (zh-array.js)
 * 支持 ES6+ 所有原生数组方法 + 链式调用（返回新数组，不修改原数组）
 * 含 JSDoc 参数提示 + 常用扩展工具方法
 */

class 数组 {
  /**
   * 构造函数 - 创建数组实例
   * @param {any[]|any} [值=[]] 初始数组内容或单个值
   */
  constructor(值 = []) {
    this._值 = Array.isArray(值) ? [...值] : [值];
  }

  /**
   * 获取当前数组的副本
   * @returns {any[]} 数组副本
   */
  取值() {
    return [...this._值];
  }

  /**
   * 打印当前数组到控制台
   * @returns {数组} 返回this以支持链式调用
   */
  打印() {
    console.log(this._值);
    return this;
  }

  /**
   * 获取数组长度
   * @returns {number} 数组长度
   */
  长度() {
    return this._值.length;
  }

  /**
   * 添加元素到数组末尾
   * @param {...any} 元素 要添加的元素
   * @returns {数组} 新的数组实例
   */
  添加(...元素) {
    return new 数组([...this._值, ...元素]);
  }

  /**
   * 在指定位置插入元素
   * @param {number} 索引 插入位置
   * @param {...any} 元素 要插入的元素
   * @returns {数组} 新的数组实例
   */
  插入(索引, ...元素) {
    const arr = [...this._值];
    arr.splice(索引, 0, ...元素);
    return new 数组(arr);
  }

  /**
   * 删除指定索引位置的元素
   * @param {number} 索引 要删除的起始位置
   * @param {number} [数量=1] 要删除的元素数量
   * @returns {数组} 新的数组实例
   */
  删除(索引, 数量 = 1) {
    const arr = [...this._值];
    arr.splice(索引, 数量);
    return new 数组(arr);
  }

  /**
   * 清空数组
   * @returns {数组} 空数组的新实例
   */
  清空() {
    return new 数组([]);
  }

  /**
   * 获取指定索引的元素
   * @param {number} 索引 元素索引
   * @returns {any} 对应索引的元素
   */
  取(索引) {
    return this._值[索引];
  }

  /**
   * 查找第一个满足条件的元素
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {any|null} 找到的元素或null
   */
  查找(回调) {
    return this._值.find(回调);
  }

  /**
   * 查找最后一个满足条件的元素
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {any|null} 找到的元素或null
   */
  查找最后(回调) {
    return this._值.findLast(回调);
  }

  /**
   * 查找第一个满足条件的元素的索引
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {number} 找到的索引或-1
   */
  查找索引(回调) {
    return this._值.findIndex(回调);
  }

  /**
   * 查找最后一个满足条件的元素的索引
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {number} 找到的索引或-1
   */
  查找最后索引(回调) {
    return this._值.findLastIndex(回调);
  }

  /**
   * 判断数组是否包含指定值
   * @param {any} 值 要检查的值
   * @returns {boolean} 是否包含
   */
  包含(值) {
    return this._值.includes(值);
  }

  /**
   * 获取指定值的第一个索引
   * @param {any} 值 要查找的值
   * @returns {number} 索引或-1
   */
  索引(值) {
    return this._值.indexOf(值);
  }

  /**
   * 获取指定值的最后一个索引
   * @param {any} 值 要查找的值
   * @returns {number} 索引或-1
   */
  最后索引(值) {
    return this._值.lastIndexOf(值);
  }

  /**
   * 遍历数组的每个元素
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {数组} 返回this以支持链式调用
   */
  遍历(回调) {
    this._值.forEach(回调);
    return this;
  }

  /**
   * 映射数组元素生成新数组
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {数组} 映射后的新数组实例
   */
  映射(回调) {
    return new 数组(this._值.map(回调));
  }

  /**
   * 过滤数组元素
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {数组} 过滤后的新数组实例
   */
  过滤(回调) {
    return new 数组(this._值.filter(回调));
  }

  /**
   * 规约数组元素
   * @param {function} 回调 回调函数，接收(累加器,元素,索引,数组)四个参数
   * @param {any} [初始值] 初始累加值
   * @returns {any} 规约结果
   */
  规约(回调, 初始值) {
    return this._值.reduce(回调, 初始值);
  }

  /**
   * 判断是否所有元素都满足条件
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {boolean} 是否全部满足
   */
  全部(回调) {
    return this._值.every(回调);
  }

  /**
   * 判断是否有任意元素满足条件
   * @param {function} 回调 回调函数，接收(元素,索引,数组)三个参数
   * @returns {boolean} 是否有满足条件的元素
   */
  某些(回调) {
    return this._值.some(回调);
  }

  /**
   * 排序数组
   * @param {function} [比较函数] 排序比较函数
   * @returns {数组} 排序后的新数组实例
   */
  排序(比较函数) {
    return new 数组([...this._值].sort(比较函数));
  }

  /**
   * 翻转数组顺序
   * @returns {数组} 翻转后的新数组实例
   */
  翻转() {
    return new 数组([...this._值].reverse());
  }

  /**
   * 拼接多个数组或元素
   * @param {...any} 数组项 要拼接的数组或元素
   * @returns {数组} 拼接后的新数组实例
   */
  拼接(...数组项) {
    const 新数组 = [...this._值];
    for (const a of 数组项) {
      if (a instanceof 数组) 新数组.push(...a._值);
      else if (Array.isArray(a)) 新数组.push(...a);
      else 新数组.push(a);
    }
    return new 数组(新数组);
  }

  /**
   * 截取数组片段
   * @param {number} [开始=0] 开始索引
   * @param {number} [结束] 结束索引（不包含）
   * @returns {数组} 切片后的新数组实例
   */
  切片(开始, 结束) {
    return new 数组(this._值.slice(开始, 结束));
  }

  /**
   * 按分隔符拼接数组元素为字符串
   * @param {string} [分隔符=","] 分隔符
   * @returns {string} 拼接后的字符串
   */
  按分隔符拼接(分隔符 = ",") {
    return this._值.join(分隔符);
  }

  /**
   * 填充数组元素
   * @param {any} 值 填充值
   * @param {number} [开始=0] 开始索引
   * @param {number} [结束=this._值.length] 结束索引（不包含）
   * @returns {数组} 填充后的新数组实例
   */
  填充(值, 开始 = 0, 结束 = this._值.length) {
    const arr = [...this._值];
    arr.fill(值, 开始, 结束);
    return new 数组(arr);
  }

  /**
   * 拷贝数组元素到目标位置
   * @param {number} 目标索引 目标位置
   * @param {number} [开始=0] 源开始索引
   * @param {number} [结束=this._值.length] 源结束索引（不包含）
   * @returns {数组} 拷贝后的新数组实例
   */
  拷贝到(目标索引, 开始 = 0, 结束 = this._值.length) {
    const arr = [...this._值];
    arr.copyWithin(目标索引, 开始, 结束);
    return new 数组(arr);
  }

  /**
   * 拍平嵌套数组
   * @param {number} [深度=1] 拍平深度
   * @returns {数组} 拍平后的新数组实例
   */
  拍平(深度 = 1) {
    return new 数组(this._值.flat(深度));
  }

  /**
   * 映射并拍平数组
   * @param {function} 回调 映射函数
   * @returns {数组} 映射并拍平后的新数组实例
   */
  拍平映射(回调) {
    return new 数组(this._值.flatMap(回调));
  }

  /**
   * 获取数组索引的迭代器
   * @returns {Iterator<number>} 索引迭代器
   */
  键迭代() {
    return this._值.keys();
  }

  /**
   * 获取数组值的迭代器
   * @returns {Iterator<any>} 值迭代器
   */
  值迭代() {
    return this._值.values();
  }

  /**
   * 获取数组条目的迭代器
   * @returns {Iterator<[number, any]>} 条目迭代器，包含[索引,值]对
   */
  条目迭代() {
    return this._值.entries();
  }

  /**
   * 数组去重
   * @returns {数组} 去重后的新数组实例
   */
  去重() {
    return new 数组([...new Set(this._值)]);
  }

  /**
   * 打乱数组顺序
   * @returns {数组} 打乱后的新数组实例
   */
  打乱() {
    const arr = [...this._值];
    for (let i = arr.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return new 数组(arr);
  }

  /**
   * 合并多个数组或元素
   * @param {...any} 数组项 要合并的数组或元素
   * @returns {数组} 合并后的新数组实例
   */
  合并(...数组项) {
    return this.拼接(...数组项);
  }

  /**
   * 找到第一个满足条件的元素的索引
   * @param {function} 回调 回调函数
   * @returns {number} 索引或-1
   */
  找索引(回调) {
    return this._值.findIndex(回调);
  }

  /**
   * 找到最后一个满足条件的元素的索引
   * @param {function} 回调 回调函数
   * @returns {number} 索引或-1
   */
  找最后索引(回调) {
    return this._值.findLastIndex(回调);
  }

  /**
   * 判断数组是否包含指定值（可指定起始位置）
   * @param {any} 值 要检查的值
   * @param {number} [起始=0] 开始检查的索引
   * @returns {boolean} 是否包含
   */
  包含值(值, 起始 = 0) {
    return this._值.includes(值, 起始);
  }

  /**
   * 转换为字符串
   * @returns {string} 字符串表示
   */
  转字符串() {
    return this._值.toString();
  }

  /**
   * 转换为本地字符串
   * @returns {string} 本地字符串表示
   */
  转本地字符串() {
    return this._值.toLocaleString();
  }

  /** 静态方法区 */

  /**
   * 静态方法：判断是否为数组
   * @static
   * @param {any} v 要检查的值
   * @returns {boolean} 是否为数组
   */
  static 是否数组(v) {
    return Array.isArray(v);
  }

  /**
   * 静态方法：从类数组或可迭代对象创建数组
   * @static
   * @param {ArrayLike|Iterable} 可迭代 类数组或可迭代对象
   * @param {function} [映射函数] 映射函数
   * @returns {数组} 新的数组实例
   */
  static 从(可迭代, 映射函数) {
    return new 数组(Array.from(可迭代, 映射函数));
  }

  /**
   * 静态方法：创建指定长度的数组
   * @static
   * @param {number} 长度 数组长度
   * @param {any} [填充值=undefined] 填充值
   * @returns {数组} 新的数组实例
   */
  static 创建(长度, 填充值 = undefined) {
    return new 数组(Array(长度).fill(填充值));
  }

  /**
   * 静态方法：合并多个数组或元素
   * @static
   * @param {...any} 数组项 要合并的数组或元素
   * @returns {数组} 合并后的新数组实例
   */
  static 合并(...数组项) {
    const 合 = [];
    for (const a of 数组项) {
      if (a instanceof 数组) 合.push(...a._值);
      else if (Array.isArray(a)) 合.push(...a);
      else 合.push(a);
    }
    return new 数组(合);
  }
}

// 同时支持 ES 模块和 CommonJS 导出
try {
  // 浏览器环境导出
  if (typeof exports === 'undefined') {
    window.数组 = 数组;
  }
} catch (e) {}

// CommonJS 导出
  module.exports = {
    数组,
    default: 数组
  };
  module.exports.数组 = 数组;


// ES 模块导出
// export { 数组 };
// export default 数组;